package filstu

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"sync"
)

//返回的文件指针
func openFile(fileName string) (*os.File, error) {
	fmt.Println("打开文件", fileName)
	return os.Open(fileName)
}

//传递指针
//实践中注意 go与java的不同 这里如果传File就是复制的值会出bug
func closeFile(file *os.File) {
	fmt.Println("关闭文件", (*file).Name())
	file.Close()
}

//defer 延迟执行
//关键字确保文件被关闭
func ParseFile(path string) {

	fPoint, err := openFile(path)
	if err != nil {
		log.Fatal("读取文件异常直接退出程序!!!")
	}
	//defer 延迟确保执行
	defer closeFile(fPoint)
	s := bufio.NewScanner(fPoint)
	for s.Scan() {
		fmt.Println(s.Text())
		//测试异常
		//b := 0
		//a := 20 / b
		//fmt.Println(a)
		break
	}
	//放这里是不会被执行的
	//defer closeFile(fPoint)
	err = s.Err()
	if err != nil {
		log.Fatal(err)
	}

}

//defer 再次加深
func LoopFunc() {
	lock := sync.Mutex{}
	for i := 0; i < 3; i++ {
		//当前线程执行完成才能执行 defer lock.Unlock()
		//在同一个线程中循环得不到释放锁.deadlock!
		//所以放go中每个单独线程才正确
		go func(i int) {
			lock.Lock()
			defer lock.Unlock()
			fmt.Println("loopFunc:", i)
		}(i)
	}
}

//当匿名函数引用了外部作用域中的变量时就成了闭包函数
func Cp() {
	for i := 0; i < 3; i++ {
		//每个defer语句延迟执行的函数引用的都是同一个i迭代变量，
		//在循环结束后这个变量的值为3，因此最终输出的都是3
		//defer func() { println(i) }()
		/*
			修改方法1 定义一个循环体内局部变量 放入作用域就不是闭包了
			i := i
			defer func ()  {
				println(i)
			}()
		*/

		//修改方法2
		// 通过函数传入i defer 语句会马上对调用参数求值
		defer func(i int) {
			println(i)
		}(i)

		//defer 类似入栈,最后的先执行到
		//2 1 0

	}
}
